<?php
/**
 * Created by PhpStorm.
 * User: tian
 * Date: 2018/3/4
 * Time: 21:59
 * 用于解析CODIS文件，支持DAT、XML文件格式
 * 调用方法：CODISDecode::instance->loadFile($path)->decode();
 */

namespace org\util\forensictool;

class CODISDecode
{
    protected $content;//codis文件内容
    protected $version;//codis文件版本
    protected static $instance;//object 对象实例

    /**
     * @return CODISDecode
     * 实例化当前类
     */
    static public function instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new static();
        }
        return self::$instance;
    }

    /**
     * @param string $path
     * @return CODISDecode
     * @throws \Exception
     * 获取文件文本
     */
    public function loadFile($path)
    {
        $this->content = file_get_contents($path);
        $info = pathinfo($path);
        $allowExt = ['dat', 'xml'];
        if (in_array(strtolower($info['extension']), $allowExt)) {
            $this->version = $info['extension'];
        } else {
            throw new \Exception('文件类型错误');
        }
        return $this;
    }

    /**
     * @return array
     * @throws \Exception
     * 按文件类型解析
     */
    public function decode()
    {
        switch ($this->version) {
            case 'dat':
                return $this->decodeDat();
                break;
            case 'xml':
                return $this->decodeXml();
                break;
            default:
                throw new \Exception('文件类型错误');
        }
    }

    /**
     * @return array
     * @throws \Exception
     */
    protected function decodeDat()
    {
        $str = $this->content;
        $sampleStrings = preg_split('/PCR\r\n/', $str);
        $allele = [];

        array_shift($sampleStrings);
        foreach ($sampleStrings as $sampleString) {
            $currentSample = [];
            $sampleName = substr($sampleString, 0, strpos($sampleString, "\r\n"));
            if (preg_match_all('/.+\r\n1\r\n.+\r\n.+\r\n.+\r\n[012][\r\n]*[\d\.XY]*[\r\n]*[\d\.Y]*/', $sampleString, $markerStrings)) {
                $markerStrings = $markerStrings[0];
                foreach ($markerStrings as $markerString) {
                    $lines = preg_split('/\r\n/', $markerString);
                    foreach ($lines as $index => $line) {
                        if ($line == ''){
                            unset($lines[$index]);
                        }
                    }
                    $markerName = $lines[0];
                    $alleleCount = $lines[5];
                    switch ($alleleCount){
                        case '0':
                            $marker = [];
                            break;
                        case '1':
                            if (substr($markerName,0,1) == 'Y' || (substr($markerName, 0 ,2) == 'DY' && $markerName != 'DYS385')){
                                $marker = isset($lines[6]) ? [$lines[6]] : [];
                            }else{
                                $marker = isset($lines[6]) ? [$lines[6], $lines[6]] : [];
                            }
                            break;
                        case '2':
                            $marker = [$lines[6],$lines[7]];
                            break;
                        default:
                            throw new \Exception('codis数据格式错误');
                    }
                    $currentSample[$markerName] = $marker;
                }
                $allele[$sampleName] = $currentSample;
            }
        }
        return $allele;
    }

    /**
     * @return array
     * @throws \Exception
     */
    protected function decodeXml()
    {
        $arr = json_decode(json_encode(simplexml_load_string($this->content)), true);
        $allele = [];
        if (isset($arr['SPECIMEN'])) {
            if (isset($arr['SPECIMEN'][0])) {
                $arr_specimen = $arr['SPECIMEN'];
            } else {
                $arr_specimen[0] = $arr['SPECIMEN'];
            }
        } else {
            throw new \Exception('codis数据格式错误');
        }
        foreach ($arr_specimen as $specimen) {
            $sampleName = $specimen['SPECIMENID'];
            foreach ($specimen['LOCUS'] as $marker) {
                $markerName = $marker['LOCUSNAME'];
                if ($marker['ALLELE'][0]) {
                    $allele[$sampleName][$markerName][0] = $marker['ALLELE'][0]['ALLELEVALUE'];
                    $allele[$sampleName][$markerName][1] = $marker['ALLELE'][1]['ALLELEVALUE'];
                } else {
                    $allele[$sampleName][$markerName][0] = $marker['ALLELE']['ALLELEVALUE'];
                    $allele[$sampleName][$markerName][1] = $marker['ALLELE']['ALLELEVALUE'];
                }
            }
        }
        return $allele;
    }

}